/**
 * @return {number}
 * @param str
 */
// let lengthOfLongestSubstring = function (str) {
//   let n = str.length
//   // 滑动窗口为s[left...right]
//   let left = 0
//   let right = -1
//   let freqMap = {} // 记录当前子串中下标对应的出现频率
//   let max = 0 // 找到的满足条件子串的最长长度
//
//   while (left < n) {
//     let nextLetter = str[right + 1]
//     if (!freqMap[nextLetter] && nextLetter !== undefined) {
//       freqMap[nextLetter] = 1
//       right++
//     } else {
//       freqMap[str[left]] = 0
//       left++
//     }
//     max = Math.max(max, right - left + 1)
//   }
//
//   return max
// }
// // @lc code=end
// let str = 'abcabcbb'
// console.log(lengthOfLongestSubstring(str))

//最长不重复子串
//lengthOfLongestSubstring解题思路
// 1. 初始化left和right指针，分别指向窗口的左右边界
// 2. 当right指针指向的字符不在当前子串中时，右指针向右移动
// 3. 当right指针指向的字符在当前子串中时，left指针向右移动
// 4. 更新最大值
// let lengthOfLongestSubstring = function (str) {
//   let n = str.length
//   // 滑动窗口为s[left...right]
//   let left = 0
//   let right = -1
//   let freqMap = {} // 记录当前子串中下标对应的出现频率===map
//   let max = 0 // 找到的满足条件子串的最长长度

//   while (left < n) { // 当left指针指向的字符不在当前子串中时，右指针向右移动
//       let nextLetter = str[right + 1]   // 当前子串的右端点的下一个字符
//     console.log(nextLetter)
//     if (!freqMap[nextLetter] && nextLetter !== undefined) { // 当前窗口右边界的下一个字符不在当前子串中
//       freqMap[nextLetter] = 1 // 将当前字符加入到当前子串中
//       right++ // 右指针向右移动
//     } else {
//       freqMap[str[left]] = 0  // 当前字符出现过，则将其出现次数减1 重新计数
//       left++  // 左指针向右移动
//     }
//     max = Math.max(max, right - left + 1) // 更新最大值
//     console.log(freqMap)
//   }

//   return max
// }

// let str = 'abcabcbb'
// console.log(lengthOfLongestSubstring(str))


// let lengthOfLongestSubstring = function (str) {
//   let n = str.length;
//   let left = 0;
//   let right = -1
//   let map = {}
//   let res =0
//   while (left < n) {
//     let nextLetter = str[right + 1];
//     if ((!map[nextLetter]===0||map[nextLetter]===undefined)&& nextLetter !== undefined) { // skip
//       map[nextLetter] = 1;
//       right++;//
//     } else {
//       map[nextLetter] = 0;//重新开始计数
//       left++;//窗口右移 
//     }
//     res = Math.max(res,right-left+1);
//   }
// return res;
// }

// let str = 'abcabcbb'
// console.log(lengthOfLongestSubstring(str))


var lengthOfLongestSubstring = function(s) {
  // 哈希集合，记录每个字符是否出现过
  const occ = new Set();
  const n = s.length;
  // 右指针，初始值为 -1，相当于我们在字符串的左边界的左侧，还没有开始移动
  let rk = -1, ans = 0;   // 初始值为 0，答案也是从 0 开始
  for (let i = 0; i < n; ++i) {
      if (i != 0) {
          // 左指针向右移动一格，移除一个字符
          occ.delete(s.charAt(i - 1));//
      }
      while (rk + 1 < n &&
      !occ.has(s.charAt(rk + 1))) {   //当set中不含有s.charAt(rk + 1))
          // 不断地移动右指针3
          occ.add(s.charAt(rk + 1));//将
          ++rk;
      }
      // 第 i 到 rk 个字符是一个极长的无重复字符子串
      ans = Math.max(ans, rk - i + 1);//
  }
  return ans;
};
let str = 'abcabcbb'
console.log(lengthOfLongestSubstring(str))